<template>
  <div class="container">
    <div id="map-container">
      <div v-show="showPopup" id="point-popup" ref="pointPopupRef">
        <PointPopup :coordinate="curCoordinate" />
      </div>
    </div>
  </div>
</template>
<script setup lang='ts'>
import { onMounted, ref } from 'vue';
import 'ol/ol.css'
import { Map, View, Feature, Overlay } from 'ol'
import VectorSource from 'ol/source/Vector'
import { Vector as VectorLayer } from 'ol/layer'
import { Style, Fill as StyleFill, Stroke as StyleStroke, Icon as StyleIcon } from 'ol/style'
import { Point as GeomPoint, LineString as GeomLineString, Polygon as GeomPolygon, Circle as GeomCircle } from 'ol/geom'
import { useTianTileLayer, projection } from '@/hooks'
import { TiandiTileLayerConfigEnum } from '@/enum'
import { CENTER_BLHX_LONG_LAT } from '@/constant'

import PointPopup from './popup/index.vue'
import type { FeatureLike } from 'ol/Feature';

let map: Map

const pointPopupRef = ref<HTMLDivElement>()
const showPopup = ref(false)
const curCoordinate = ref<number[]>([])

onMounted(() => {
  initMap()
})

// 初始化地图
function initMap() {
  map = new Map({
    target: 'map-container',
    layers: [ ...useTianTileLayer(TiandiTileLayerConfigEnum.YX) ],
    view: new View({
      center: CENTER_BLHX_LONG_LAT,
      zoom: 3,
      maxZoom: 17,
      minZoom: 1,
      projection: projection,
    })
  })
  getCoordinate()
  addEvent()
}

// 获取坐标
function getCoordinate() {
  // 根据坐标 添加点、线
  const coordinates = [
    [170.168644,60.003816],
    [196.219216,59.930029],
    [216.373455,34.240125]
  ]
  addLine(coordinates)
  addPoint(coordinates)

  // 根据坐标添加多边形（闭合坐标）
  const polygonCoordinate = [
    [[166.8694094393246, 38.5937762931288],[181.61306824626664,38.5937762931288],[181.61306824626664,56.38445792017218],[166.8694094393246,56.38445792017218],[166.8694094393246,38.5937762931288]],
    [[177.79450274691308,56.7337361931269],[179.64343803567178,55.307034572956],[178.84212051053865,53.11342352289949],[181.00214800160643,54.00129764283258],[182.50121213441105, 52.21053078454137],[182.81230433672013,54.525106524645366],[185.11268599465788,54.92795071641066],[183.26375070589918,56.354652336581566],[184.0650682310323,58.54826338663807],[181.90504073996453, 57.66038926670498],[180.40597660715991,59.451156124996196],[180.09488440485083,57.1365803848922],[177.79450274691308,56.7337361931269 ]]
  ]
  addPolygon(polygonCoordinate)
  
  // 根据圆心坐标、半径添加圆
  const circleCoordinate = [-179.80138,14.384928]
  const radius = 1000000 // 1千千米
  addCircle(circleCoordinate, getRadius(radius))
}

/**
 * 获取转换后单位的半径
 * @param radius 以米为单位的半径的值
 */
function getRadius(radius: number) {
  let metersPerUnit = map.getView().getProjection().getMetersPerUnit()!;
  let circleRadius = radius / metersPerUnit;
  return circleRadius;
}

/**
 * 添加线 传入多个坐标即可
 * @param coordinates 
 */
function addLine(coordinates: Array<number[]>) {
  if(!map) return
  const Line = new Feature({
    type: 'line',
    geometry: new GeomLineString(coordinates),
  });
  Line.setStyle(new Style({
    fill: new StyleFill({
      color: 'rgba(255, 255, 255, 0.2)'
    }),
    stroke: new StyleStroke({
      color: 'red',
      width: 1
    })
  }))
  const vectorSource = new VectorSource({
    features: [Line]
  })
  const vectorLayer = new VectorLayer({
    source: vectorSource
  })
  map.addLayer(vectorLayer)
  return { Line, vectorSource, vectorLayer }
}

/**
 * 添加点 传入多个坐标点 二维数组 全部添加
 * @param coordinates 
 */
function addPoint(coordinates: number[][]) {
  const features: Array<Feature<GeomPoint>> = []
  coordinates.forEach(coordinate => {
    const Point = new Feature({
      type: 'point',
      geometry: new GeomPoint(coordinate)
    })
    // 为每个点设置数据
    Point.set('data', {
      name: 'WFT',
      age: 18
    })
    //设置点1的样式信息
    Point.setStyle(new Style({
      // image: new StyleCircle({
      //   radius: 5,
      //   fill: new StyleFill({
      //     color: '#ffcc33'
      //   })
      // })
      image: new StyleIcon({
        src: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
        scale: 0.05
      })
    }))
    features.push(Point)
  })
  const vectorSource = new VectorSource({
    // features: [Point]
  })
  vectorSource.addFeatures(features)
  const vectorLayer = new VectorLayer({
    source: vectorSource
  })
  map.addLayer(vectorLayer)
  return { features, vectorSource, vectorLayer }
}

/**
 * 添加多边形
 * @param polygons 
 */
function addPolygon(polygons: number[][][]) {
  const Polygon = new Feature({
    type: 'Polygon',
    geometry: new GeomPolygon(polygons)
  })
  //设置点1的样式信息
  Polygon.setStyle(new Style({
    //填充色
    fill: new StyleFill({
      color: 'yellow'
    }),
    //边线颜色
    stroke: new StyleStroke({
      color: 'red',
      width: 2
    })
  }))
  const vectorSource = new VectorSource({
    features: [Polygon]
  })
  const vectorLayer = new VectorLayer({
    source: vectorSource
  })
  map.addLayer(vectorLayer)
  return { vectorSource, vectorLayer }
}

/**
 * 添加圆
 * @param coordinate 圆心坐标
 * @param radius 半径
 */
function addCircle(coordinate: number[], radius: number) {
  const Circle = new Feature({
    type: 'Circle',
    geometry: new GeomCircle(coordinate, radius)
  })
  //设置点1的样式信息
  Circle.setStyle(new Style({
    //填充色
    fill: new StyleFill({
      color: 'rgba(239, 118, 19, 0.6)'
    }),
    //边线颜色
    stroke: new StyleStroke({
      color: 'red',
      width: 2
    })
  }))
  const vectorSource = new VectorSource({
    features: [Circle]
  })
  const vectorLayer = new VectorLayer({
    source: vectorSource
  })
  map.addLayer(vectorLayer)
  return { vectorSource, vectorLayer }
}


function addEvent() {
  map.on('pointermove', e => {
    const pixel = map.getEventPixel(e.originalEvent);
    const hit = map.hasFeatureAtPixel(pixel);
    if(hit) {
      map.getTargetElement().style.cursor = 'pointer'
      if(map.getOverlays().getLength()) {
        map.getOverlays().clear()
      }
      const feature = map.forEachFeatureAtPixel(e.pixel, feature => feature) as FeatureLike
      if(feature) {
        const coordinates = (feature.getGeometry() as any).getCoordinates();
        if((feature as FeatureLike & { values_: {[key: string]: any} }).values_.type == 'point') {
          let data = feature.get('data')
          console.log(data, '获取当前点设置的数据信息-->>')
          addOverlay(coordinates || e.pixel)
          curCoordinate.value = coordinates
        }
      }
    } else {
      map.getTargetElement().style.cursor = ''
      if(map.getOverlays().getLength()) {
        map.getOverlays().clear()
      }
      showPopup.value = false
    }
  })
}

// 添加popup弹出
function addOverlay(coordinates: Array<number>) {
  const popup = new Overlay({
    //要转换成overlay的HTML元素
    element: pointPopupRef.value,
    //当前窗口可见
    autoPan: false,
    //Popup放置的位置
    positioning: 'bottom-center',
    //是否应该停止事件传播到地图窗口
    stopEvent: false
  });
  map.addOverlay(popup);
  popup.setPosition(coordinates)
  showPopup.value = true
}
</script>
<style scoped>
.container {
  width: 100%;
  height: 100%;
  position: relative;
}

#map-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9;
}

#point-popup {
  width: 280px;
  height: 200px;
  position: absolute;
  top: -50px;
  right: 20px;
  z-index: 0;
}
</style>